/**
 * 版权所有(C)，上海海鼎信息工程股份有限公司，2009，所有权利保留。
 * 
 * 项目名：	rumba-widget2
 * 文件名：	RDecoratorPanel.java
 * 模块说明：	
 * 修改历史：
 * Jan 18, 2009 - lxm - 创建。
 */
package com.hd123.rumba.gwt.widget2.client.panel;

import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * 带修饰的面板，即在普通的面板外面加一个边框，利用CSS可以获得例如阴影的现实效果。
 * <p>
 * 
 * <b>CSS Style Rules<b>
 * <ol type=disc>
 * <li>.rb-DecoratorPanel { 整个面板 }</li>
 * <li>.rb-DecoratorPanel .top { 顶边行 }</li>
 * <li>.rb-DecoratorPanel .topLeft { 左上角单元格 }</li>
 * <li>.rb-DecoratorPanel .topLeftInner { 左上角单元格的内部元素 }</li>
 * <li>.rb-DecoratorPanel .topCenter { 上边单元格 }</li>
 * <li>.rb-DecoratorPanel .topCenterInner{ 上边单元格的内部元素 }</li>
 * <li>.rb-DecoratorPanel .topRight { 右上角单元格 }</li>
 * <li>.rb-DecoratorPanel .topRightInner { 右上角单元格的内部元素 }</li>
 * <li>.rb-DecoratorPanel .middle { 中间行 }</li>
 * <li>.rb-DecoratorPanel .middleLeft { 左边单元格 }</li>
 * <li>.rb-DecoratorPanel .middleLeftInner { 左边单元格的内部元素 }</li>
 * <li>.rb-DecoratorPanel .middleCenter { 中间单元格 }</li>
 * <li>.rb-DecoratorPanel .middleCenterInner { 中间单元格的内部元素 }</li>
 * <li>.rb-DecoratorPanel .middleRight { 右边单元格 }</li>
 * <li>.rb-DecoratorPanel .middleRightInner { 右边单元格的内部元素 }</li>
 * <li>.rb-DecoratorPanel .bottom { 底边行 }</li>
 * <li>.rb-DecoratorPanel .bottomLeft { 左下角单元格 }</li>
 * <li>.rb-DecoratorPanel .bottomLeftInner { 左下角单元格的内部元素 }</li>
 * <li>.rb-DecoratorPanel .bottomCenter { 下边单元格 }</li>
 * <li>.rb-DecoratorPanel .bottomCenterInner { 下边单元格的内部元素 }</li>
 * <li>.rb-DecoratorPanel .bottomRight { 右下角单元格 }</li>
 * <li>.rb-DecoratorPanel .bottomRightInner { 右下角单元格的内部元素 }</li>
 * </ol>
 * 
 * @author lxm
 * 
 */
public class RDecoratorPanel extends SimplePanel {
  /**
   * The default style name.
   */
  private static final String DEFAULT_STYLENAME = "rb-DecoratorPanel";

  /**
   * The default styles applied to each row.
   */
  private static final String[] DEFAULT_ROW_STYLENAMES = {
      "top", "middle", "bottom" };

  /**
   * Create a new row with a specific style name. The row will contain three
   * cells (Left, Center, and Right), each prefixed with the specified style
   * name.
   * 
   * This method allows Widgets to reuse the code on a DOM level, without
   * creating a DecoratorPanel Widget.
   * 
   * @param styleName
   *            the style name
   * @return the new row {@link Element}
   */
  static Element createTR(String styleName) {
    Element trElem = DOM.createTR();
    setStyleName(trElem, styleName);
    DOM.appendChild(trElem, createTD(styleName + "Left"));
    DOM.appendChild(trElem, createTD(styleName + "Center"));
    DOM.appendChild(trElem, createTD(styleName + "Right"));
    return trElem;
  }

  /**
   * Create a new table cell with a specific style name.
   * 
   * @param styleName
   *            the style name
   * @return the new cell {@link Element}
   */
  private static Element createTD(String styleName) {
    Element tdElem = DOM.createTD();
    Element inner = DOM.createDiv();
    DOM.appendChild(tdElem, inner);
    setStyleName(tdElem, styleName);
    setStyleName(inner, styleName + "Inner");
    return tdElem;
  }

  /**
   * The container element at the center of the panel.
   */
  private Element containerElem;

  /**
   * The table body element.
   */
  private Element tbody;

  /**
   * Create a new {@link DecoratorPanel}.
   */
  public RDecoratorPanel() {
    this(DEFAULT_ROW_STYLENAMES, 1);
  }

  /**
   * Creates a new panel using the specified style names to apply to each row.
   * Each row will contain three cells (Left, Center, and Right). The Center
   * cell in the containerIndex row will contain the {@link Widget}.
   * 
   * @param rowStyles
   *            an array of style names to apply to each row
   * @param containerIndex
   *            the index of the container row
   */
  RDecoratorPanel(String[] rowStyles, int containerIndex) {
    super(DOM.createTable());

    // Add a tbody
    Element table = getElement();
    tbody = DOM.createTBody();
    DOM.appendChild(table, tbody);
    DOM.setElementPropertyInt(table, "cellSpacing", 0);
    DOM.setElementPropertyInt(table, "cellPadding", 0);

    // Add each row
    for (int i = 0; i < rowStyles.length; i++) {
      Element row = createTR(rowStyles[i]);
      DOM.appendChild(tbody, row);
      if (i == containerIndex) {
        containerElem = DOM.getFirstChild(DOM.getChild(row, 1));
      }
    }

    // Set the overall style name
    setStyleName(DEFAULT_STYLENAME);
  }

  /**
   * Get a specific Element from the panel.
   * 
   * @param row
   *            the row index
   * @param cell
   *            the cell index
   * @return the Element at the given row and cell
   */
  protected Element getCellElement(int row, int cell) {
    Element tr = DOM.getChild(tbody, row);
    Element td = DOM.getChild(tr, cell);
    return DOM.getFirstChild(td);
  }

  protected Element getContainerElement() {
    return containerElem;
  }
}
